import axios from 'axios'
import { Message, MessageBox, Notification } from 'element-ui'
import cache from './cache'

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 错误码映射
const errorCode = {
  400: '请求错误',
  401: '未授权，请重新登录',
  403: '拒绝访问',
  404: '请求地址出错',
  405: '请求方法不被允许',
  408: '请求超时',
  500: '服务器内部错误',
  501: '服务未实现',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时',
  505: 'HTTP版本不受支持',
  default: '系统未知错误'
}

// 防止重复提交标识
let isRelogin = { show: false }

/**
 * 参数处理
 */
function tansParams(params) {
  let result = ''
  for (const prop in params) {
    if (Object.prototype.hasOwnProperty.call(params, prop) && params[prop] !== null && params[prop] !== undefined) {
      result += `&${prop}=${params[prop]}`
    }
  }
  return result
}

/**
 * 获取token（简化版，直接获取）
 */
function getToken() {
  return JSON.parse(localStorage.getItem('vue-next-admin:access-token')) || JSON.parse(sessionStorage.getItem('vue-next-admin:access-token'))
}
function decryptJWT  (token) {
    // 将所有下划线替换为斜杠，将所有破折号替换为加号，以使令牌有效的base64编码
    token = token.replace(/_/g, "/").replace(/-/g, "+");

    // 解码令牌的base64编码的有效载荷，并将其转换为JSON字符串
    const json = decodeURIComponent(escape(window.atob(token.split(".")[1])));

    // 解析JSON字符串并返回结果对象
    return JSON.parse(json);
}
function getJWTDate (timestamp) {
    // 通过将时间戳乘以1000来将其转换为毫秒，并创建一个新的Date对象
    return new Date(timestamp * 1000);
}
// request拦截器
service.interceptors.request.use(config => {
  // 设置token
  const token = getToken()

  const isToken = (config.headers || {}).isToken === false
  if (token && !isToken) {
    config.headers['Authorization'] = token
      const jwt = decryptJWT(token); 
  if (new Date() >= getJWTDate(jwt.exp)) { // 判断访问令牌是否过期
        var refreshAccessToken = JSON.parse(window.localStorage.getItem('vue-next-admin:x-access-token')); // 获取刷新令牌
        if (refreshAccessToken){
           config.headers["X-Authorization"] = refreshAccessToken.startsWith("Bearer ") ? refreshAccessToken : `Bearer ${refreshAccessToken}`; // 如果刷新令牌存在，添加到头部对象
        } 
    }
  }
  // 根据请求方法处理参数
  const method = config.method.toLowerCase()
  
  if (method === 'get' || method === 'delete') {
     // GET/DELETE请求：参数拼接到URL
  if (config.params && Object.keys(config.params).length > 0) {
    const paramsStr = tansParams(config.params)
    // 去掉开头的 &，因为 tansParams 返回的是 &key=value&key2=value2
    const cleanParams = paramsStr.startsWith('&') ? paramsStr.substring(1) : paramsStr
    config.url = config.url + '?' + cleanParams
    config.params = {}
  }
  } else if (method === 'post' || method === 'put') {
    // POST/PUT请求：参数放在body中
    const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
    
    // 防止重复提交
    if (!isRepeatSubmit) {
      const requestObj = {
        url: config.url,
        data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
        time: new Date().getTime()
      }
      const sessionObj = cache.session.getJSON('sessionObj')
      if (sessionObj) {
        const s_url = sessionObj.url
        const s_data = sessionObj.data
        const s_time = sessionObj.time
        const interval = 1000
        if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
          const message = '数据正在处理，请勿重复提交'
          console.warn(`[${s_url}]: ` + message)
          return Promise.reject(new Error(message))
        }
      }
      cache.session.setJSON('sessionObj', requestObj)
    }
  }
  
  return config
}, error => {
  console.log('请求拦截器错误:', error)
  return Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
  // 未设置状态码则默认成功状态
  const code = res.data.code || 200
  // 获取错误信息
  const msg = errorCode[code] || res.data.msg || errorCode['default']
  
  // 二进制数据则直接返回
  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    return res.data
  }
  
  if (code === 401) {
    if (!isRelogin.show) {
      isRelogin.show = true
      MessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', { 
        confirmButtonText: '重新登录', 
        cancelButtonText: '取消', 
        type: 'warning' 
      }).then(() => {
        isRelogin.show = false
        // 清除token并跳转到登录页
        localStorage.removeItem('vue-next-admin:access-token')
          localStorage.removeItem('vue-next-admin:x-access-token')
        sessionStorage.removeItem('vue-next-admin:access-token')
          sessionStorage.removeItem('vue-next-admin:x-access-token')
        window.location.href = getLoginPath()
      }).catch(() => {
        isRelogin.show = false
      })
    }
    return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
  } else if (code === 500) {
    Message({ message: msg, type: 'error' })
    return Promise.reject(new Error(msg))
  } else if (code === 601) {
    Message({ message: msg, type: 'warning' })
    return Promise.reject('error')
  } else if (code !== 200) {
    Notification.error({ title: msg })
    return Promise.reject('error')
  } else {
    RefreshToken(res)
    return res.data
  }
}, error => {
  console.log('响应拦截器错误:', error)
  let { message } = error
  if (message === 'Network Error') {
    message = '后端接口连接异常'
  } else if (message.includes('timeout')) {
    message = '系统接口请求超时'
  } else if (message.includes('Request failed with status code')) {
    message = '系统接口' + message.substr(message.length - 3) + '异常'
  }
  Message({ message: message, type: 'error', duration: 5 * 1000 })
  return Promise.reject(error)
})
function RefreshToken(res){
  
   var accessToken = res.headers.get("access-token");//res.getResponseHeader("access-token");
    var refreshAccessToken = res.headers.get("x-access-token"); //res.getResponseHeader("x-access-token");
    ValidateToken(accessToken, refreshAccessToken);
}
function ValidateToken (accessToken, refreshAccessToken) {
    // 判断是否是无效 token
    if (accessToken === "invalid_token") {
        window.location.href = getLoginPath()
    }
    // 判断是否存在刷新 token，如果存在则存储在本地
    else if (
        refreshAccessToken &&
        accessToken &&
        accessToken !== "invalid_token"
    ) {
      localStorage.setItem('vue-next-admin:access-token', JSON.stringify(accessToken));
      localStorage.setItem('vue-next-admin:x-access-token', JSON.stringify(refreshAccessToken));
    }
}
function getLoginPath() {
  const currentPath = window.location.pathname
  // 检查是否部署在子目录下
  if (currentPath.includes('/dist/')) {
    return '/dist/login'  // 如果是hash模式
    // 或者 return '/dist/login'  // 如果是history模式
  }
  return '/login'  // 如果是hash模式
  // 或者 return '/login'  // 如果是history模式
}
/**
 * 导出默认的request函数，支持对象配置
 * 这样就可以使用你原来的调用方式了
 */
export default service